package jnexus.utils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings( "rawtypes" )
public class ReflectTools {
	/**
	 * Cria uma instancia de uma dada classe.
	 * 
	 * @param klass
	 * @return T
	 */
	@SuppressWarnings( "unchecked" )
	public static <T> T instance( Class klass ) {
		T object = null;
		try {
			Constructor<?>[] constructors = klass.getConstructors();

			Constructor<?> c = constructors[0];

			if ( c != null ) {
				List<Object> params = new ArrayList<Object>();
				for ( Class<?> type : c.getParameterTypes() )
					if ( type.isPrimitive() ) {
						if ( type.equals( int.class ) )
							params.add( new Integer( 0 ) );
						else if ( type.equals( float.class ) )
							params.add( new Float( 0 ) );
						else if ( type.equals( double.class ) )
							params.add( new Double( 0.0 ) );
						else if ( type.equals( char.class ) )
							params.add( new Character( '0' ) );
						else if ( type.equals( long.class ) )
							params.add( new Long( 0 ) );
					} else
						params.add( null );
				object = (T) klass.cast( c.newInstance( params.toArray() ) );
			}

		} catch ( InstantiationException e ) {
			e.printStackTrace();
		} catch ( IllegalAccessException e ) {
			e.printStackTrace();
		} catch ( IllegalArgumentException e ) {
			e.printStackTrace();
		} catch ( InvocationTargetException e ) {
			e.printStackTrace();
		}
		return object;
	}

	/**
	 * Retorna todos os atributos da classe.
	 * 
	 * @param klass
	 * @return List
	 */
	public static List<Field> getFields( Class klass ) {
		List<Field> fields = new ArrayList<Field>();
		for ( Class k : getParents( klass ) )
			for ( Field field : k.getDeclaredFields() )
				fields.add( field );
		return fields;
	}

	/**
	 * Retorna todas as super classes incluindo a propria classe ( Não retorna a
	 * classe Object )
	 * 
	 * @param klass
	 * @return List
	 */
	public static List<Class> getParents( Class klass ) {
		List<Class> parents = new ArrayList<Class>();
		parents.add( obtainparents( klass, parents ) );
		return parents;
	}

	private static Class obtainparents( Class klass, List<Class> list ) {
		if ( klass.getSuperclass().equals( Object.class ) )
			return klass;
		list.add( obtainparents( klass.getSuperclass(), list ) );
		return klass;
	}
}
